using System.ComponentModel;

namespace DrawerMenu.Services;

public class NavigationService : INavigationService, INotifyPropertyChanged
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Dictionary<Type, Type> _viewModelToViewMap;
    private object? _currentView;

    public object? CurrentView
    {
        get => _currentView;
        private set
        {
            _currentView = value;
            OnPropertyChanged(nameof(CurrentView));
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    public NavigationService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        _viewModelToViewMap = new Dictionary<Type, Type>();
    }

    public void RegisterMapping<TViewModel, TView>() 
        where TViewModel : class 
        where TView : class
    {
        _viewModelToViewMap[typeof(TViewModel)] = typeof(TView);
    }

    public void NavigateTo<TViewModel>() where TViewModel : class
    {
        NavigateTo(typeof(TViewModel));
    }

    public void NavigateTo(Type viewModelType)
    {
        if (!_viewModelToViewMap.TryGetValue(viewModelType, out var viewType))
        {
            throw new InvalidOperationException($"No view registered for ViewModel type {viewModelType.Name}");
        }

        var view = _serviceProvider.GetService(viewType);
        if (view == null)
        {
            throw new InvalidOperationException($"Could not resolve view type {viewType.Name}");
        }

        var viewModel = _serviceProvider.GetService(viewModelType);
        if (viewModel == null)
        {
            throw new InvalidOperationException($"Could not resolve ViewModel type {viewModelType.Name}");
        }

        if (view is System.Windows.FrameworkElement frameworkElement)
        {
            frameworkElement.DataContext = viewModel;
        }

        CurrentView = view;
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
